package com.meterhuang;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * 大数的加法和乘法
 * @author meterhuang
 * @since 2021/03/29
 */
@Slf4j
public class BigDataCompute {

    public static void main(String[] args) {
        bigDataMultiply();
    }

    public static void bigDataMultiply() {
        String num1 = "488888";
        String num2 = "399888";
        // 对于乘法，两个数相乘的结果最大位数为两个数位数之和
        int max = num1.length() + num2.length();
        String[] arr = new String[max];
        String multiply = multiply(num1, num2, arr);
        log.info("{}", StringUtils.reverse(multiply));
    }

    public static void bigDataAdd() {
        String num1 = "19999999999";
        String num2 = "99999999999";
        int l1 = num1.length();
        int l2 = num2.length();
        // 对于加法，两个数之和最大位数为两者之中位数较大者加1位
        int max;
        if (l1 > l2) {
            max = l1 + 1;
        } else {
            max = l2 + 1;
        }
        String[] arr = new String[max];
        String add = add(num1, num2, arr);
        log.info("{}", StringUtils.reverse(add));
    }

    private static String multiply(String num1, String num2, String[] arr) {
        for (int i = num1.length() - 1; i >= 0 ; i--) {
            int number1 = num1.charAt(i) - '0';
            // 从低位开始存储
            int index = num1.length() - i - 1;
            for (int j = num2.length() - 1; j >= 0; j--) {
                int number2 = num2.charAt(j) - '0';
                int multiply = number1 * number2;
                multiplyRecursive(arr, index, multiply);
                index += 1;
            }
        }
        return StringUtils.join(arr, "");
    }

    private static String add(String num1, String num2, String[] arr) {
        String[] arr1 = new String[arr.length];
        String[] arr2 = new String[arr.length];
        for (int i = num1.length() - 1; i >= 0; i--) {
            int number1 = num1.charAt(i) - '0';
            int index = num1.length() - i - 1;
            arr1[index] = number1 + "";
        }
        for (int j = num2.length() - 1; j >= 0; j--) {
            int number2 = num2.charAt(j) - '0';
            int index = num2.length() - j - 1;
            arr2[index] = number2 + "";
        }
        for (int index = 0; index < arr.length; ++ index) {
            if (arr1[index] == null) {
                arr1[index] = "0";
            }
            if (arr2[index] == null) {
                arr2[index] = "0";
            }
            int add = Integer.valueOf(arr1[index]) + Integer.valueOf(arr2[index]);
            if (add >= 10) {
                if (arr[index] != null) {
                    int sum = Integer.valueOf(arr[index]) + add;
                    arr[index] = (sum % 10) + "";
                    arr[index + 1] = (sum / 10) + "";
                } else {
                    arr[index] = add % 10 + "";
                    arr[index + 1] = 1 + "";
                }
            } else {
                if (arr[index] == null) {
                    arr[index] = add + "";
                } else {
                    int sum = Integer.valueOf(arr[index]) + add;
                    arr[index] = sum % 10 + "";
                    if (sum >= 10) {
                        arr[index + 1] = sum / 10 + "";
                    }
                }
            }
        }

        return StringUtils.join(arr, "");
    }

    private static void multiplyRecursive(String[] arr, int index, int num) {
        int mod = num % 10;
        int quotient = num / 10;
        if (arr[index] == null) {
            try {
                arr[index] = mod + "";
                // 避免最后一位数组越界
                if (quotient > 0) {
                    arr[index + 1] = quotient + "";
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        } else {
            int sum = Integer.valueOf(arr[index]) + mod;
            if (sum >= 10 || quotient > 0) {
                arr[index] = (sum % 10) + "";
                multiplyRecursive(arr, index + 1, sum / 10 + quotient);
            } else {
                arr[index] = sum + "";
                return;
            }
        }
    }
}
